import Axios from "axios";
import NProgress from "../progress";
import { showFailToast } from "vant";
import { getToken, getShareToken } from "../auth";

import "vant/es/toast/style";

// 是否使用Xmate base url
let baseUrl = import.meta.env.VITE_XMATE_BASE_API;

// 默认 axios 实例请求配置
const configDefault = {
  headers: {
    "Content-Type": "application/json"
  },
  timeout: 300000,
  baseURL: baseUrl,
  data: {}
};

let source = Axios.CancelToken.source();

export class Http {
  constructor(config) {
    Http.axiosConfigDefault = config;
    Http.axiosInstance = Axios.create(config);
    this.httpInterceptorsRequest();
    this.httpInterceptorsResponse();
  }
  // 当前实例
  static axiosInstance;
  // 请求配置
  static axiosConfigDefault;

  // 请求拦截
  httpInterceptorsRequest() {
    Http.axiosInstance.interceptors.request.use(
      config => {
        if (!config.disableProgress) {
          NProgress.start();
        }
        // 发送请求前，可在此携带 token
        const token = getToken();
        if (token) {
          config.headers["token"] = token;
        }
        const shareToken = getShareToken();
        if (shareToken) {
          config.headers["Authorization"] = shareToken;
        }
        const userInfoStr = localStorage.getItem("yxt-userInfo");
        const userInfo = JSON.parse(userInfoStr);
        const isBlue = import.meta.env.VITE_ENV === "blue";
        if (isBlue) {
          config.headers["yxt-orgdomain"] = "salesmate.yunxuetang.cn";
        } else {
          config.headers["yxt-orgdomain"] = userInfo.ssoDomain || "";
        }
        config.headers["clientType"] = "h5";
        if (config.useStream) {
          config.dataType = "text/event-stream";
        }
        return config;
      },
      error => {
        showFailToast(error.message);
        return Promise.reject(error);
      }
    );
  }

  // 响应拦截
  httpInterceptorsResponse() {
    Http.axiosInstance.interceptors.response.use(
      response => {
        const { useStream, useOriginRes, disableToast } = response.config;
        if (useOriginRes) {
          NProgress.done();
          return response.data;
        }
        if (!useStream) {
          NProgress.done();
          const { code, message, data } = response.data;
          const isSuccess = code === 0;
          if (isSuccess) {
            return data;
          } else {
            // 处理请求错误
            if (!disableToast) {
              console.error("处理请求错误: ", message);
              showFailToast(message);
            }
            return Promise.reject(response.data);
          }
        } else {
          const reader = response.body
            .pipeThrough(new TextDecoderStream())
            .getReader();
          let answer = "";
          let lastIdx = 0;
          let end = false;

          while (!end) {
            reader.read().then(({ value, done }) => {
              if (done) {
                reader.releaseLock();
                end = true;
              }
              answer += value;
            });
          }
        }
      },
      error => {
        NProgress.done();
        // 处理 HTTP 网络错误
        let message = "";

        if (error.code === "ERR_CANCELED") {
          // 手动取消请求
          return Promise.reject(error);
        }
        // HTTP 状态码
        const status = error.response?.status;
        switch (status) {
          case 400:
            message = "请求错误";
            break;
          case 401:
            message = "未授权，请登录";
            break;
          case 403:
            message = "拒绝访问";
            break;
          case 404:
            message = `请求地址出错: ${error.response?.config?.url}`;
            break;
          case 408:
            message = "请求超时";
            break;
          case 500:
            message = "服务器内部错误";
            break;
          case 501:
            message = "服务未实现";
            break;
          case 502:
            message = "网关错误";
            break;
          case 503:
            message = "服务不可用";
            break;
          case 504:
            message = "网关超时";
            break;
          case 505:
            message = "HTTP版本不受支持";
            break;
          default:
            message = `网络连接故障(${status})`;
        }

        console.error("处理请求错误 error: ", message);
        showFailToast(message);
        error.message = message;
        return Promise.reject(error);
      }
    );
  }

  // 通用请求函数
  request(paramConfig) {
    const config = { ...Http.axiosConfigDefault, ...paramConfig };
    return new Promise((resolve, reject) => {
      config.cancelToken = source.token;
      Http.axiosInstance
        .request(config)
        .then(response => {
          if (!config.useStream) {
            resolve(response);
          }
        })
        .catch(error => {
          reject(error);
        });
    });
  }

  // 取消请求
  cancel() {
    source.cancel("stop by user.");
    source = Axios.CancelToken.source();
  }
}

const controller = new AbortController();
const { signal } = controller;

export const cancelFetchRequest = () => {
  controller.abort();
};

export async function fetchPost(url, data, callBack) {
  url = configDefault.baseURL + url;
  let headers = {
    "Content-Type": "application/json"
  };
  const token = getToken();
  if (token) {
    headers["token"] = token;
  }
  const response = await fetch(url, {
    method: "POST",
    headers,
    dataType: "text/event-stream",
    body: JSON.stringify(data),
    signal
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  const chatId = response.headers.get("Chat-id");
  //;
  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
  let buffer = "";
  let lastIdx = 0;
  while (true) {
    const readData = await reader.read();
    const { done, value } = readData;
    if (done) {
      reader.releaseLock();
      break;
    }
    buffer += value;
    let lines = buffer.split("\n");
    for (let i = 0; i < lines.length - 1; i++) {
      let line = lines[i].trim();
      if (!line.startsWith("data:")) continue;
      line = line.slice(5).trim();
      let chunkObj;
      try {
        if (line.startsWith("{")) {
          chunkObj = JSON.parse(line);
        } else {
          continue;
        }
      } catch (error) {
        console.error("Error parsing chunk:", error);
        continue;
      }
      callBack(chunkObj, chatId);
    }
    buffer = lines[lines.length - 1];
  }
}

export const http = new Http(configDefault);

const xmateConfigDefault = {
  headers: {
    "Content-Type": "application/json"
  },
  timeout: 30000,
  baseURL: import.meta.env.VITE_XMATE_BASE_API,
  data: {}
};
// 这里域名变了使用新的
export const xmateHttp = new Http(xmateConfigDefault);
